Subject: Netbios Names and Circuits

From: [email-masked] (Paul Brittain)
Date: Wed, 1 Jun 94 12:28:43 BST

Steve/Connect RIGlet,

Here is the note I promised last week on the subject of 15/16 byte Netbios
Names.

There are several issues wrapped up together in this area that we discovered
while testing our Netbios support against 6611s (MPNP R1.2).  These are classic
interoperability issues in that there is no easily identifiable 'right' or
'wrong' answer, but lots of grey ones that won't work together.  If we are to
avoid similar problems with standard DLSw implementations, we must, at minimum,
make the Netbios documentation more precise than in the current RFC.

The rest of this note explains:

-       how the 6611 uses the SSP protocol for Netbios circuits
-       why this is a grey area
-       suggested resolution.

Paul Brittain
Data Connection

6611 SSP USAGE FOR NETBIOS
==========================

This information was derived from watching the TCP/IP traffic between two 6611s
during MS LANMAN logon/data transfers between OS/2 end-stations.  Our own
implementation interoperates with the 6611 using the flows documented here, so
that gives me confidence that we haven't completely misunderstood how the 6611
supports Netbios.  However I apologise in advance to IBM if we have
misunderstood anything and hence appear to misrepresent the 6611.  If so,
please post a correction!

MS LANMAN uses 15 byte Netbios names - but the 16th byte is still significant,
though I'm not sure of its precise use.  The basic flow when LANMAN sets up a
session between 2 workstations is shown below, without DLSw for the moment.  I
have used 'Sniffer' notation for the Netbios names i.e. NAME1<05> denotes the
name  'NAME1' padded with spaces but with x05 in the 16th byte.

        STATION1                                        STATION2
        ========                                        ========

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<05>,NAME1<03>)
        ------------------------------------------------>

        NAME_QUERY(NAME2<03>,NAME1<03>)
        ------------------------------------------------>

                     NAME_RECOGNIZED(NAME1<03>,NAME2<03>)
        <------------------------------------------------

        SABME
        ------------------------------------------------>

                                                      UA
        <------------------------------------------------

  ....I-frame/UI traffic not significant to this discussion....

As shown above:

-       LANMAN issues a full set of Netbios retries for the x05 name first
-       It then switches to trying the x03 name.

I have not attempted to show the broadcast types for each frame as they are
only what you would expect from the frame formats in the IBM LAN Tech Reference
chapter 5.

If 'NAME2' was not present on the network we would see a full set of Netbios
retries for the x03 name too before the connection attempt is aborted.

Now let's add in two 6611s.  This time we'll assume that NAME2 is not present
on either LAN so we get the full set of Netbios retries.  You'll have to
forgive me if I change my notation as the 'full' names for each frame type
don't fit in 80 characters!  I'll use NQx05 or NETBIOS_NQx05 to denote the LAN
and SSP versions respectively of a NAME_QUERY with x05 in the 16th byte.

LAN1            6611A                           6611B                   LAN2
====            =====                           =====                   ====

NQx05            NETBIOS_NQx05                   NQx05
---------------->------------------------------->----------------------->
NQx05                                            NQx05
---------------->} retries               local  { ----------------------->
NQx05            }                              { NQx05
---------------->} are                   retries{ ----------------------->
NQx05            }                              { NQx05
---------------->} absorbed              at     { ----------------------->
NQx05            }                              { NQx05
---------------->} at origin             target { ----------------------->
NQx05            }                              { NQx05
---------------->} DLSw                  DLSw   { ----------------------->

NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->

As is shown above, the x03 NAME_QUERY frames are always passed across to the
target DLSw with no retry absorption at the origin.  The reason for this is
contained in the way the 6611 uses circuit IDs for Netbios, which is as
follows:

SSP Frame               Circuit ID Carried
---------               ------------------

NETBIOS_NQx05           Specifies the origin Port and Transport IDs.  DLC
                        correlator is NULL (binary 0).

NETBIOS_NQx03           Specifies the same origin Port and Transport IDs.

NETBIOS_NR              Always carries the origin Port and Transport IDs from
                        the NETBIOS_NQx05 even if the partner DLSw specifies
                        different values on the NETBIOS_NQx03.  The target DLC
                        correlator is NULL (cf. the ICR for SNA circuits)

REACH_ACK               Origin DLC correlator filled in.

CONTACT                 Nothing unusual.

CONTACTED               Target DLC correlator is filled in (cf. SNA circuits
                        where this flows on the ICR).

GREY AREAS
==========

The flows and circuit ID usage described above highlight several unclear or
unsatisfactory areas that we need to resolve on this RIGlet:

1)      Do we support 15 or 16 byte Netbios names?

        The processing described above is not compatible with 16 byte names so
        this should be optional.  However will a potential DLSw user be able to
        restrict all his uses of Netbios to either 15 or 16 byte names?  This
        seems unlikely so we ought to try to support both concurrently.

2)      When are circuit IDs resolved?

        SNA circuits resolve the circuit ID on the ICR/RA exchange.  The
        current RFC and discussions to-date on this RIGlet have treated the
        NQ/NR as equivalent to the CUR/ICR, but this is not the case in the
        flows documented above.

        See also my previous posting on the need to document when the circuit
        ID is fixed during SSP circuit setup.

3)      Unwanted persistence of NETBIOS_NQ information.

        The 6611 currently retains knowledge of the partial circuit ID
        specified on the NETBIOS_NQx05 even after the first NETBIOS_NRx03
        has flowed.  This restricts the flexibility of use for the Port ID or
        transport ID and forces the origin DLSw to retain the same information
        after the local retry period has completed.  In particular, the 6611
        retains the Port ID from the NETBIOS_NQx05 as the origin Port ID for
        any circuit that is eventually setup using the x03 names.  This makes
        it impossible to use different Port ID fields for the x05 and x03
        NETBIOS_NQ messages even though these are supposed to be of local
        significance only.

4)      Excess WAN traffic.

        Because of the persistence of the NQ data and the change in the 16th
        byte of the Netbios name, the retries of the NQx03 are passed directly
        through the WAN.   This becomes an issue if the name is not present on
        any network (e.g. a server is down) because every connection attempt
        requires 7 NETBIOS_NQ frames, each 151 bytes long (on my network) over
        a three second period.  This may also be multiplied up for each
        additional DLSw partner to which the NQ must be broadcast.

        It should be possible to get the remote DLSw to handle the retries of
        the x03 name instead.

5)      Frequency of change of 16th byte

        LANMAN uses only a couple of values for the 16th byte.  Is this true
        for all Netbios implementations/applications?  If the 16th byte could
        be different on each retry, this would pull us in the opposite
        direction to the previous issue and more towards the current 6611
        solution!

WHAT NEXT?
==========

The current 6611 implementation certainly works and we have been able to
interoperate with it.  However it fails to solve issues 1 and 2 and exacerbates
issues 3 and 4.  On the other hand, issue 5 demonstrates that there is no
'right' solution here.

In discussions here at DCL we came up with the following potential
alternative.  It solves issues 1 to 4, though it would be less efficient in the
scenario envisaged in 5.  It is also, unfortunately, incompatible with the
current solution because of the way the 6611 carries over circuit IDs.

Please review this proposal and post comments on the following:

-       Should we try to solve these issues?
-       Do we have time to do so in release 1?
-       Which is more important to solve: issue 4 or issue 5?

The following proposal is based on the answers 'Yes', 'Yes' and '4'
respectively, so it may not correspond to the direction the RIGlet chooses.
However it does represent an alternative for discussion.

PROPOSED SOLUTION
=================

This solution assumes that, given the choice of creating an additional control
block locally versus passing multiple retries on the WAN, the local control
block is the lesser evil.

The key difference between this solution and the current 6611 implementation is
that this solution assumes 16 byte name significance as the default but will
resolve names that match to 15 bytes if necessary.  It will effectively treat
LANMAN names as 16 byte significant, but the fall-back to 15 bytes allows for
a Netbios implementation/application that does not pass back the same 16th
byte in the NR as specified in the NQ.

The detailed processing in this proposal is as follows:

-       When receiving a NQ from the LAN, a DLSw always treats all 16 bytes as
        significant in the names.  This will cause it to create two control
        blocks during a LANMAN circuit setup sequence, one each for the NQx05
        and the NQx03.

-       Retries on a NQ on the LAN are absorbed as long as the control block
        still exists, otherwise they are treated as a new setup attempt.

-       Control blocks are timed out if they remain in the DISCONNECTED state
        (i.e. the circuit setup fails).  The timeout period is locally
        configurable.

-       The target DLSw behaves similarly for each NETBIOS_NQ received over
        TCP/IP.

-       When it receives a NR over the LAN, the target DLSw tries to match it
        against any outstanding NETBIOS_NQ control blocks using 16 byte name
        significance.  If this fails, it could (optionally?) try for a 15 byte
        match.

-       If a match is found, the target DLSw sets up whatever circuit control
        block it needs in order to be able to send a NETBIOS_NR back to the
        origin DLSw with the full circuit ID specified.

-       On receipt of a NETBIOS_NR, the origin DLSw matches the name specified
        in exactly the same way as the target searched for a match.  If a match
        is found, it sends the NR on the LAN, sets up a circuit control block
        and sends an RA with the fully specified circuit ID.  If no match is
        found, the origin DLSw returns a HALT_DL_NO_ACK to tidy up the circuit.

-       Circuit setup then follows the usual FSM as the SABME and UA flow.

-       Any NQ/NR control blocks that were set up but never resolved (e.g. the
        NQx05 for LANMAN) are eventually timed out and discarded.

Using this solution we would see the following flows for an unsuccessful LANMAN
circuit setup attempt.  Note the reduction of the WAN traffic.

LAN1            DLSwA                           DLSwB                   LAN2
====            =====                           =====                   ====

NQx05            NETBIOS_NQx05                   NQx05
---------------->------------------------------->----------------------->
NQx05                                            NQx05
---------------->} retries               local  { ----------------------->
NQx05            }                              { NQx05
---------------->} are                   retries{ ----------------------->
NQx05            }                              { NQx05
---------------->} absorbed              at     { ----------------------->
NQx05            }                              { NQx05
---------------->} at origin             target { ----------------------->
NQx05            }                              { NQx05
---------------->} DLSw                  DLSw   { ----------------------->

NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03                                            NQx03
---------------->} retries               local  { ----------------------->
NQx03            }                              { NQx03
---------------->} are                   retries{ ----------------------->
NQx03            }                              { NQx03
---------------->} absorbed              at     { ----------------------->
NQx03            }                              { NQx03
---------------->} at origin             target { ----------------------->
NQx03            }                              { NQx03
---------------->} DLSw                  DLSw   { ----------------------->

A successful LANMAN circuit setup shows a similar flow to that seen under the
existing solution, but there will be an additional control block left on either
side that will eventually be timed out.

LAN1            DLSwA                           DLSwB                   LAN2
====            =====                           =====                   ====

NQx05            NETBIOS_NQx05                   NQx05
---------------->------------------------------->----------------------->
NQx05                                            NQx05
---------------->} retries               local  { ----------------------->
NQx05            }                              { NQx05
---------------->} are                   retries{ ----------------------->
NQx05            }                              { NQx05
---------------->} absorbed              at     { ----------------------->
NQx05            }                              { NQx05
---------------->} at origin             target { ----------------------->
NQx05            }                              { NQx05
---------------->} DLSw                  DLSw   { ----------------------->

NQx03            NETBIOS_NQx03                   NQx03
---------------->------------------------------->----------------------->
NQx03            NETBIOS_NQx03                   NRx03
<----------------<-------------------------------<-----------------------
                 | RA
                 ------------------------------->
SABME            CONTACT                         SABME
---------------->------------------------------->----------------------->
UA               CONTACTED                       UA
<----------------<-------------------------------<-----------------------

A few possible further refinements spring to mind:

-       Capex exchange of whether 15 byte names are supported.
-       Capex exchange of NQ/NR timeouts.
-       Use of a partial circuit ID on the NQ to speed resolution of the
        NR when it is returned.

I am in favour of the first enhancement and wary of the other two.  What does
everyone else think?